package com.itita.ww2.game.alliance;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.itita.ww2.core.TaskPerSecond;
import com.itita.ww2.core.TaskPerSecond.ITimerCondition;
import com.itita.ww2.core.WW2Exception;
import com.itita.ww2.data.AllianceConfig;
import com.itita.ww2.data.AllianceConfig.AlRoleType;
import com.itita.ww2.data.AllianceConfig.PermType;
import com.itita.ww2.enums.WW2ExceptionCode;
import com.itita.ww2.game.alliance.enums.AlJoinLimitType;
import com.itita.ww2.game.alliance.event.AllianceEventDispatch;
import com.itita.ww2.game.alliance.event.IAllianceMemberJoinListener.JoinType;
import com.itita.ww2.game.alliance.event.IAllianceMemberRoleChangedListener.ChangedType;
import com.itita.ww2.game.enums.ContributeType;
import com.itita.ww2.game.enums.StateEnum;
import com.itita.ww2.game.user.UserService;
import com.itita.ww2.game.user.event.UserEventDispatch;
import com.itita.ww2.game.worldmap.WorldMapManager;
import com.itita.ww2.model.enums.AlWMDataFields;
import com.itita.ww2.model.user.UserProfile;
import com.itita.ww2.puredb.model.Alliance;
import com.itita.ww2.puredb.model.AllianceJoinRequest;
import com.itita.ww2.puredb.model.AllianceJoinRequestKey;
import com.itita.ww2.puredb.model.AllianceMember;
import com.itita.ww2.puredb.model.AllianceUserQuitCD;
import com.itita.ww2.puredb.model.UserAllianceLog;
import com.itita.ww2.puredb.model.UserAllianceLogKey;
import com.itita.ww2.redis.RedisUtil;
import com.itita.ww2.utils.TimeUtil;
import com.itita.ww2.utils.UUIDGenerator;
import com.lambdaworks.redis.KeyValue;
import com.lambdaworks.redis.ScoredValue;
import com.smartfoxserver.v2.entities.data.ISFSArray;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.entities.data.SFSObject;

public class AllianceService {
	private static final Logger logger = LoggerFactory.getLogger(AllianceService.class);

	/**
	 * 联盟是否已经存在
	 */
	public static final boolean isAllianceExists(String name) {
		Alliance ret = Alliance.getByName(name);
		return ret != null;
	}

	/**
	 *  检查权限
	 */
	private static final AllianceMember checkPerm(AllianceMember m_Am, AllianceMember t_Am, PermType permType)
			throws WW2Exception {
		if (t_Am == null) {
			if (!AllianceConfig.hasPermission(m_Am.getRole(), -1, permType)) {
				throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NO_PERMISSION);
			}
		} else {
			if (!AllianceConfig.hasPermission(m_Am.getRole(), t_Am.getRole(), permType)) {
				throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NO_PERMISSION);
			}
		}
		return m_Am;
	}

	/**
	 * 查询所有联盟信息<br>
	 * 支持分页查询
	 */
	public static ISFSObject getAllAllianceData(int page) {
		Collection<Alliance> als = AllianceManager.getInstance().getAllAlliance();
		List<List<Alliance>> als_partition = Lists.partition(new ArrayList<>(als), AllianceConfig.pageCount);
		int pageCount = als_partition.size();
		if (page > als_partition.size()) {
			return SFSObject.newInstance();
		}
		List<Alliance> al_page = als_partition.get(page - 1);

		ISFSArray list = SFSArray.newInstance();
		for (Alliance item : al_page) {
			list.addSFSObject(getAllianceData(item));
		}

		ISFSObject ret = SFSObject.newInstance();
		ret.putSFSArray("list", list);
		ret.putBool("isLastPage", page == pageCount);
		return ret;
	}

	/**
	 * 获取所有加盟请求<br>
	 * 支持分页查询
	 */
	public static ISFSObject getAllJoinRequest(UserProfile userProfile, int page) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.JOIN_RECEIPT);

		PageHelper.startPage(page, AllianceConfig.pageCount);
		List<AllianceJoinRequest> m_Ajrs = AllianceJoinRequest.getByAid(userProfile.getAid());
		PageInfo<AllianceJoinRequest> pageInfo = new PageInfo<>(m_Ajrs);

		ISFSArray list = SFSArray.newInstance();
		for (AllianceJoinRequest item : m_Ajrs) {
			UserProfile itemProfile = UserService.getInstance().getUserProfile(item.getUid());
			if (itemProfile == null) {
				logger.warn("UserProfile [uid:{}] not found!", item.getUid());
				continue;
			}
			ISFSObject obj = SFSObject.newInstance();
			obj.putInt("uid", itemProfile.getUid());
			obj.putUtfString("nickname", userProfile.getNickname());
			obj.putUtfString("country", userProfile.getCountry());
			obj.putInt("lv", userProfile.getUserInfo().getLevel());
			//
			list.addSFSObject(obj);
		}
		ISFSObject ret = SFSObject.newInstance();
		ret.putSFSArray("list", list);
		ret.putBool("isLastPage", pageInfo.isIsLastPage());
		return ret;
	}

	/**
	 * 根据联盟ID查询联盟成员信息<br>
	 * 支持分页查询,每页数量N
	 */
	public static ISFSObject getAllAllianceUserByAid(String aid, int page) {
		ISFSObject ret = SFSObject.newInstance();

		PageHelper.startPage(page, AllianceConfig.pageCount);
		List<AllianceMember> m_Ams = AllianceMember.getByAid(aid);

		PageInfo<AllianceMember> pageInfo = new PageInfo<>(m_Ams);

		ISFSArray list = SFSArray.newInstance();
		for (AllianceMember item : m_Ams) {
			list.addSFSObject(getAllianceUserData(item));
		}

		ret.putSFSArray("list", list);
		ret.putBool("isLastPage", pageInfo.isIsLastPage());
		return ret;
	}

	public static ISFSObject getAllianceUserData(AllianceMember member) {
		UserProfile userProfile = UserService.getInstance().getUserProfile(member.getUid());
		if (userProfile == null) {
			logger.warn("UserProfile [uid:{}] can not found!", member.getUid());
			return SFSObject.newInstance();
		}
		ISFSObject ret = member.toSFSObject();
		ret.putUtfString("nickname", userProfile.getNickname());
		ret.putUtfString("country", userProfile.getCountry());
		ret.putBool("online", userProfile.isLogin());
		ret.putInt("lv", userProfile.getUserInfo().getLevel());
		ret.putInt("vipLv", userProfile.getUserInfo().getVipLv());
		return ret;
	}

	/**
	 * 获取联盟数据
	 */
	public static ISFSObject getAllianceData(UserProfile userProfile) {
		return getAllianceData(userProfile, null);
	}

	public static ISFSObject getAllianceData(UserProfile userProfile, Alliance alliance) {
		if (!userProfile.isJoinAlliance()) {
			return SFSObject.newInstance();
		}
		if (alliance == null) {
			alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		}
		if (alliance == null) {
			logger.warn("Alliance {} not found!", userProfile.getAid());
			return SFSObject.newInstance();
		}
		AllianceMember m_Am = AllianceMember.getByUid(userProfile.getUid());
		if (m_Am == null) {
			logger.warn("AllianceMember aid:{} uid:{} not found!", userProfile.getUid(), userProfile.getAid());
			return SFSObject.newInstance();
		}
		// 历史
		UserAllianceLog m_Ual = UserAllianceLog
				.getByPrimaryKey(new UserAllianceLogKey(userProfile.getUid(), userProfile.getAid()));
		int hisBaseContribution = 0;
		int hisPayContribution = 0;
		if (m_Ual != null) {
			hisBaseContribution = m_Ual.getBaseContribution();
			hisPayContribution = m_Ual.getPayContribution();
		}
		boolean isFirstJoinAl = userProfile.getUserInfo().isFirstJoinAl();
		if (isFirstJoinAl) {
			userProfile.getUserInfo().setFirstJoinAl(false);
		}
		ISFSObject ret = getAllianceData(alliance);
		ret.putInt("role", m_Am.getRole());
		ret.putLong("joinTime", m_Am.getJointime());
		ret.putInt("mCurBaseContribution", m_Am.getBaseContribution());
		ret.putInt("mCurPayContribution", m_Am.getPayContribution());
		ret.putInt("mHisBaseContribution", hisBaseContribution);
		ret.putInt("mHisPayContribution", hisPayContribution);
		ret.putBool("mTransfer", m_Am.isTransfer());
		ret.putBool("first", isFirstJoinAl);
		return ret;
	}

	/**
	 * 获取联盟数据
	 */
	public static ISFSObject getAllianceData(Alliance alliance) {
		ISFSObject ret = alliance.toSFSObject();
		// maxMember
		ret.putInt("maxMember", getAllianceMaxMember(alliance));
		// ownerName
		UserProfile ownerProfile = UserService.getInstance().getUserProfile(ret.getInt("ownerUid"));
		if (ownerProfile == null) {
			logger.warn("UserProfile [{}] not found!", ret.getInt("ownerUid"));
		} else {
			ret.putUtfString("ownerName", ownerProfile.getNickname());
		}
		return ret;
	}

	private static int getAllianceMaxMember(Alliance alliance) {
		// TODO 40 读表
		return AllianceConfig.getDefaultMember() + alliance.getExpansion() * 40;
	}

	/**
	 * 重启联盟任务<br>
	 * 关服时间计算在内
	 */
	public static void restartAllianceTask() {
		Collection<Alliance> als = AllianceManager.getInstance().getAllAlliance();
		for (Alliance item : als) {
			if (item.isDisband()) {
				final long disbandTime = item.getDisbandtime();
				// 建立解散任务
				TaskPerSecond.addTask(AllianceConfig.disbandPrefix + item.getAid(), new ITimerCondition() {
					@Override
					public boolean condition() {
						long newTime = disbandTime + (AllianceConfig.getDisbandTime() * 1000);
						long nowTime = TimeUtil.getUtcNowMillis();
						return newTime <= nowTime;
					}
				}, () -> {
					disbandAlliance(item);
				}, true);
			}
			if (item.isTransfer()) {
				UserProfile m_Profile = UserService.getInstance().getUserProfile(item.getOwnerUid());
				AllianceMember m_Am = AllianceMember.getByUid(item.getOwnerUid()); // 盟主
				AllianceMember t_Am = AllianceMember.getByAidWithTransferNoUid(item.getAid(), m_Profile.getUid());
				if (t_Am == null) {
					continue;
				}
				UserProfile t_Profile = UserService.getInstance().getUserProfile(t_Am.getUid());
				final long transferTime = item.getTransfertime();
				// 重新建立转换任务
				TaskPerSecond.addTask(AllianceConfig.transferPrefix + item.getAid(), new ITimerCondition() {
					@Override
					public boolean condition() {
						long tmp = transferTime + AllianceConfig.getTransferDuration() * 1000;
						return tmp <= TimeUtil.getUtcNowMillis();
					}
				}, () -> {
					transferAlliance(m_Profile, t_Profile, item, m_Am, t_Am);
				}, true);
			}
		}
	}

	/**
	 * 发起解散联盟请求
	 */
	public static void disbandAllianceRequest(UserProfile userProfile) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.DISBAND);

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			throw new WW2Exception(WW2ExceptionCode.SQLEXCEPTION);
		}

		// 处于解散状态
		if (alliance.isDisband()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_DISBANDING_STATUS);
		}

		// 处于转让状态
		if (alliance.isTransfer()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_TRANSFERING);
		}

		// 处于宣战状态
		if (WorldMapManager.getInstance().isAllianceDeclared(alliance.getAid())) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_WM_WAR_STATUS);
		}

		// 设定解散状态
		alliance.setDisband(true);
		alliance.setDisbandtime(TimeUtil.getUtcNowMillis());
		alliance.update();

		final long disbandTime = alliance.getDisbandtime();

		// 建立解散任务
		TaskPerSecond.addTask(AllianceConfig.disbandPrefix + alliance.getAid(), new ITimerCondition() {
			@Override
			public boolean condition() {
				long newTime = disbandTime + (AllianceConfig.getDisbandTime() * 1000);
				long nowTime = TimeUtil.getUtcNowMillis();
				return newTime <= nowTime;
			}
		}, () -> {
			disbandAlliance(alliance);
		}, true);

		AllianceEventDispatch.onAllianceDisband(alliance, StateEnum.REQUEST);
	}

	/**
	 * 取消解散联盟
	 */
	public static void cancelDisbandAlliance(UserProfile userProfile) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.DISBAND);

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			throw new WW2Exception(WW2ExceptionCode.SQLEXCEPTION);
		}

		// 不是解散状态
		if (!alliance.isDisband()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NOT_DISBAND_STATUS);
		}

		alliance.setDisband(false);
		alliance.setDisbandtime(0);
		alliance.update();

		// 移除解散任务
		TaskPerSecond.removeTask(AllianceConfig.disbandPrefix + alliance.getAid());

		AllianceEventDispatch.onAllianceDisband(alliance, StateEnum.CANCEL);
	}

	/**
	 * 直接解散一个联盟
	 */
	private static void disbandAlliance(Alliance alliance) {
		if (!alliance.isDisband()) {
			logger.warn("Alliance [{}:{}] disband task has been cancelled", alliance.getAid(), alliance.getName());
			return;
		}

		AllianceEventDispatch.onAllianceDisband(alliance, StateEnum.DOING);

		String aid = alliance.getAid();
		// 解
		alliance.delete();

		/* 清理 */
		// 玩家表
		List<AllianceMember> m_Ams = AllianceMember.getByAid(aid);
		for (AllianceMember item : m_Ams) {
			UserProfile userProfile = UserService.getInstance().getUserProfile(item.getUid());
			if (userProfile != null) {
				userProfile.setAid("");
			}
		}
		AllianceMember.deleteByAid(aid);
		// 请求表
		AllianceJoinRequest.deleteAllByAid(aid);

		// 事件
		AllianceEventDispatch.onAllianceDisband(alliance, StateEnum.SUCCESS);

		AllianceManager.getInstance().removeAlliance(aid);
	}

	/**
	 * 转让联盟盟主
	 */
	public static void transferAllianceRequest(UserProfile userProfile, UserProfile targetProfile) throws WW2Exception {
		// 联盟必须处于非转让状态
		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NOT_EXISTS);
		}
		if (alliance.isTransfer()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_TRANSFERING);
		}
		// 处于解散状态
		if (alliance.isDisband()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_DISBANDING_STATUS);
		}

		AllianceMember m_Am = AllianceMember.getByUid(userProfile.getUid());
		AllianceMember t_Am = AllianceMember.getByUid(targetProfile.getUid());

		checkPerm(m_Am, t_Am, PermType.TRANSFER);

		// 被转让玩家必须加入联盟X秒后才能被转让

		long tempTime = t_Am.getJointime() + AllianceConfig.getTransferTimeCondition() * 1000;
		if (TimeUtil.getUtcNowMillis() < tempTime) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_TRANSFER_TIME_NOT_PERIOD);
		}
		long transferTime = TimeUtil.getUtcNowMillis();

		t_Am.setTransfer(true);
		t_Am.update();

		alliance.setTransfer(true);
		alliance.setTransfertime(transferTime);
		alliance.update();

		// 开启定时转让任务
		TaskPerSecond.addTask(AllianceConfig.transferPrefix + userProfile.getAid(), new ITimerCondition() {
			@Override
			public boolean condition() {
				long tmp = transferTime + AllianceConfig.getTransferDuration() * 1000;
				return tmp <= TimeUtil.getUtcNowMillis();
			}
		}, () -> {
			transferAlliance(userProfile, targetProfile, alliance, m_Am, t_Am);
		}, true);

		AllianceEventDispatch.onAllianceTransfer(userProfile, targetProfile, null, t_Am, alliance, StateEnum.REQUEST);
	}

	/**
	 * 取消转让盟主的请求
	 */
	public static void cancelTransferAlliance(UserProfile userProfile) throws WW2Exception {
		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NOT_EXISTS);
		}
		if (!alliance.isTransfer()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NOT_TRANSFER);
		}

		AllianceMember m_Am = AllianceMember.getByUid(userProfile.getUid()); // 盟主
		AllianceMember t_Am = AllianceMember.getByAidWithTransferNoUid(alliance.getAid(), userProfile.getUid());
		if (t_Am == null) {
			throw new WW2Exception();
		}
		UserProfile t_Profile = UserService.getInstance().getUserProfile(t_Am.getUid());

		alliance.setTransfer(false);
		alliance.setTransfertime(0);
		alliance.update();
		t_Am.setTransfer(false);
		t_Am.update();

		TaskPerSecond.removeTask(AllianceConfig.transferPrefix + userProfile.getAid());

		AllianceEventDispatch.onAllianceTransfer(userProfile, t_Profile, m_Am, t_Am, alliance, StateEnum.CANCEL);
	}

	/**
	 * 转让盟主runable
	 */
	private static void transferAlliance(UserProfile source, UserProfile target, Alliance alliance,
			AllianceMember sourceMember, AllianceMember targetMember) {
		UserAllianceLog m_ContributionLog = UserAllianceLog
				.getByPrimaryKey(new UserAllianceLogKey(source.getUid(), source.getAid()));
		int contribution = 0;
		if (m_ContributionLog != null) {
			contribution = m_ContributionLog.getTotalContribution();
		}
		AllianceMember s_AllianceMember = sourceMember;
		if (s_AllianceMember == null) {
			s_AllianceMember = AllianceMember.getByUid(source.getUid());
		}

		AllianceMember t_AllianceMember = targetMember;
		if (t_AllianceMember == null) {
			t_AllianceMember = AllianceMember.getByUid(target.getUid());
		}

		alliance.setTransfer(false);
		alliance.setTransfertime(0);
		alliance.update();

		if (contribution >= AllianceConfig.getMinCTB(AlRoleType.SERGEANCY)) {
			s_AllianceMember.setRole(AllianceConfig.getRole(AlRoleType.SERGEANCY));
		} else {
			s_AllianceMember.setRole(AllianceConfig.getRole(AlRoleType.SOLDIER));
		}
		s_AllianceMember.setTransfer(false);
		s_AllianceMember.update();

		t_AllianceMember.setRole(AllianceConfig.getRole(AlRoleType.LEADER));
		t_AllianceMember.setTransfer(false);
		t_AllianceMember.update();

		AllianceEventDispatch.onAllianceTransfer(source, target, s_AllianceMember, t_AllianceMember, alliance,
				StateEnum.SUCCESS);
	}

	/**
	 * 修改联盟参数
	 */
	public static void modifyAllianceAttr(UserProfile userProfile, ISFSObject params) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		boolean hasChanged = false;
		if (params.containsKey("declar")) {
			checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.MODIFY_DECLAR);
			alliance.setDeclar(params.getUtfString("declar"));
			hasChanged = true;
		}
		if (params.containsKey("notice")) {
			checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.MODIFY_NOTICE);
			alliance.setNotice(params.getUtfString("notice"));
			hasChanged = true;
		}
		if (params.containsKey("joinLimit")) {
			checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.MODIFY_JOINLIMIT);
			alliance.setJoinlimit(params.getInt("joinLimit"));
			hasChanged = true;
		}
		if (params.containsKey("name")) {
			checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.MODIFY_NAME);
			alliance.setName(params.getUtfString("name"));
			hasChanged = true;
		}
		if (hasChanged == true) {
			alliance.update();
		}
		AllianceEventDispatch.onAllianceInfoUpdate(alliance, params);
	}

	/**
	 * 罢免职位
	 */
	public static void recallAllianceMember(UserProfile userProfile, UserProfile targetProfile) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		AllianceMember m_tAm = AllianceMember.getByUid(targetProfile.getUid());
		if (m_tAm == null) {
			throw new WW2Exception();
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), m_tAm, PermType.RECALL);

		UserAllianceLog userAlContributionLog = UserAllianceLog
				.getByPrimaryKey(new UserAllianceLogKey(targetProfile.getUid(), targetProfile.getAid()));
		int hisContribution = 0;
		if (userAlContributionLog != null) {
			hisContribution = userAlContributionLog.getTotalContribution();
		}

		// 根据历史贡献计算需要降级到哪个职位
		if (hisContribution >= AllianceConfig.getMinCTB(AlRoleType.SERGEANCY)) {
			m_tAm.setRole(AllianceConfig.getRole(AlRoleType.SERGEANCY));
		} else {
			m_tAm.setRole(AllianceConfig.getRole(AlRoleType.SOLDIER));
		}
		m_tAm.update();

		AllianceEventDispatch.onAllianceMemberRoleChanged(userProfile, targetProfile, m_tAm, ChangedType.RECALL);
	}

	/**
	 * 任命职位
	 */
	public static void appointAllianceMember(UserProfile userProfile, UserProfile targetProfile, int targetRole)
			throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), AllianceMember.getByUid(targetProfile.getUid()),
				PermType.APPOINT);

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			throw new WW2Exception();
		}
		// 检查对应职位数
		List<AllianceMember> m_Ams = AllianceMember.getByAid(userProfile.getAid());
		int nowTarRoleCount = (int) m_Ams.stream().filter(p -> p.getRole() == targetRole).count();
		if (nowTarRoleCount >= AllianceConfig.getRoleCount(AlRoleType.valueOf(targetRole), alliance.getLevel())) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_OFFICIAL_FULL);
		}

		AllianceMember m_Am = m_Ams.stream().filter(p -> p.getUid() == targetProfile.getUid()).findFirst().orElse(null);
		if (m_Am == null) {
			throw new WW2Exception();
		}
		// 玩家处于被转让状态是无法被任命的
		if (m_Am.isTransfer()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_TRANSFERING);
		}

		m_Am.setRole(targetRole);
		m_Am.update();

		AllianceEventDispatch.onAllianceMemberRoleChanged(userProfile, targetProfile, m_Am, ChangedType.APPOINT);
	}

	/**
	 * T人
	 */
	public static void kickAllianceMember(UserProfile userProfile, UserProfile targetProfile) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		checkPerm(AllianceMember.getByUid(userProfile.getUid()), AllianceMember.getByUid(targetProfile.getUid()),
				PermType.KICKUSER);

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		removeAllianceMember(userProfile, targetProfile, alliance, true);
	}

	/**
	 * 玩家主动退出联盟
	 */
	public static void quitAlliancce(UserProfile userProfile) throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}
		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		removeAllianceMember(null, userProfile, alliance, false);
	}

	/**
	 * 回执加入联盟的请求
	 */
	public static void joinAllianceReceipt(UserProfile userProfile, UserProfile targetProfile, boolean receipt)
			throws WW2Exception {
		if (!userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		AllianceMember m_Am = checkPerm(AllianceMember.getByUid(userProfile.getUid()), null, PermType.JOIN_RECEIPT);

		// 处理互斥情况
		AllianceMember m_TAm = AllianceMember.getByUid(targetProfile.getUid());
		if (m_TAm != null) {
			AllianceJoinRequest.deleteAll(targetProfile.getUid());
			throw new WW2Exception(WW2ExceptionCode.REQUEST_ALREADY_DISPOSE);
		}

		// 超时判定
		AllianceJoinRequest m_Ajr = AllianceJoinRequest
				.getByPrimaryKey(new AllianceJoinRequestKey(targetProfile.getUid(), userProfile.getAid()));
		if (m_Ajr == null) {
			throw new WW2Exception(WW2ExceptionCode.REQUEST_ALREADY_DISPOSE);
		}
		long newTime = m_Ajr.getTime() + (AllianceConfig.getJoinRequestTime() * 1000);
		if (TimeUtil.getUtcNowMillis() > newTime) {
			m_Ajr.delete();
			throw new WW2Exception(WW2ExceptionCode.REQUEST_TIMEOUT);
		}

		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		// 接受/拒绝 申请
		if (receipt) {
			addAllianceMember(userProfile, targetProfile, alliance, AlRoleType.SOLDIER, JoinType.ACCEPT_REQUEST);
			AllianceJoinRequest.deleteAll(targetProfile.getUid());
		} else {
			if (m_Ajr != null) {
				m_Ajr.delete();
			}
			AllianceEventDispatch.onAllianceRejectJoin(userProfile, targetProfile, alliance, m_Am);
		}
	}

	/**
	 * 加入联盟请求
	 */
	public static ISFSObject joinAllianceRequest(UserProfile userProfile, String aid) throws WW2Exception {
		if (userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_ALREADY_JOIN);
		}

		Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
		if (alliance == null) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NOT_EXISTS); // 联盟不存在
		}

		// CD判定
		AllianceUserQuitCD m_Auqc = AllianceUserQuitCD.getByUid(userProfile.getUid());
		if (m_Auqc != null) {
			// cd时间判定
			long newTime = m_Auqc.getQuitTime() + (AllianceConfig.getJoinCD() * 1000);
			if (TimeUtil.getUtcNowMillis() <= newTime) {
				throw new WW2Exception(WW2ExceptionCode.ALLIANCE_JOIN_COOLDOWN);
			} else {
				m_Auqc.delete();
			}
		}

		int joinLimit = alliance.getJoinlimit();
		switch (AlJoinLimitType.valueOf(alliance.getJoinlimit())) {
		case OPEN:
			{
				addAllianceMember(null, userProfile, alliance, AlRoleType.SOLDIER, JoinType.DIRCET_JOIN);
				AllianceJoinRequest.deleteAll(userProfile.getUid());
				// 
				ISFSObject ret = SFSObject.newInstance();
				ret.putSFSObject("data", getAllianceData(userProfile, alliance));
				ret.putInt("joinLimit", joinLimit);
				return ret;// 回调 
			}
		case INVITE_ONLY:
			{
				// 发出请求(如果原本存在,刷新请求时间)
				AllianceJoinRequest m_Ajr = AllianceJoinRequest
						.getByPrimaryKey(new AllianceJoinRequestKey(userProfile.getUid(), aid));
				if (m_Ajr != null) {
					m_Ajr.setTime(TimeUtil.getUtcNowMillis());
					m_Ajr.update();
				} else {
					m_Ajr = new AllianceJoinRequest();
					m_Ajr.setAid(alliance.getAid());
					m_Ajr.setUid(userProfile.getUid());
					m_Ajr.setTime(TimeUtil.getUtcNowMillis());
					m_Ajr.insert();
				}
				ISFSObject ret = SFSObject.newInstance();
				ret.putInt("joinLimit", joinLimit);
				return ret;
			}
		case CLOSED:
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_CLOSED);
		default:
			return null;
		}
	}

	/**
	 * 移除联盟成员
	 */
	public static void removeAllianceMember(UserProfile source, UserProfile target, Alliance alliance, boolean isKicked)
			throws WW2Exception {
		if (!target.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_HAS_NOT_JOIN);
		}

		AllianceMember m_Am = AllianceMember.getByUid(target.getUid());
		if (m_Am == null) {
			throw new WW2Exception();
		}
		if (m_Am.getRole() == AllianceConfig.getRole(AlRoleType.LEADER)) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_QUIT_IS_LEADER);
		}
		// 被转让者是无法退出联盟的
		if (m_Am.isTransfer()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_TRANSFERING);
		}

		// 退出
		if (m_Am != null) {
			m_Am.delete();
		}

		AllianceUserQuitCD m_Auqc = null;
		if (!isKicked) {
			m_Auqc = new AllianceUserQuitCD();
			m_Auqc.setUid(target.getUid());
			m_Auqc.setQuitTime(TimeUtil.getUtcNowMillis());
			m_Auqc.insert();
		}
		// 
		alliance.removeMember();
		target.setAid("");
		AllianceManager.getInstance().removeAllianceUser(target);

		AllianceEventDispatch.onAllianceMemberRemoved(source, target, alliance, m_Am, m_Auqc, isKicked);
	}

	/**
	 * 添加联盟成员
	 */
	public static AllianceMember addAllianceMember(UserProfile source, UserProfile target, Alliance alliance,
			AlRoleType role, JoinType joinType) throws WW2Exception {
		if (target.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_ALREADY_JOIN);
		}

		// 人满
		if (alliance.getCurmember() >= getAllianceMaxMember(alliance)) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_IS_FULL);
		}

		AllianceMember am = AllianceMember.getByUid(target.getUid());
		if (am != null) {
			am.setAid(alliance.getAid());
			am.setJointime(TimeUtil.getUtcNowMillis());
			if (role == AlRoleType.SOLDIER) {
				UserAllianceLog m_Ual = UserAllianceLog
						.getByPrimaryKey(new UserAllianceLogKey(target.getUid(), alliance.getAid()));
				int hisContribution = 0;
				if (m_Ual != null) {
					hisContribution = m_Ual.getTotalContribution();
				}
				if (hisContribution >= AllianceConfig.getMinCTB(AlRoleType.SERGEANCY)) {
					am.setRole(AllianceConfig.getRole(AlRoleType.SERGEANCY));
				} else {
					am.setRole(AllianceConfig.getRole(AlRoleType.SOLDIER));
				}
			} else {
				am.setRole(AllianceConfig.getRole(role));
			}
			am.update();
		} else {
			am = new AllianceMember();
			am.setAid(alliance.getAid());
			am.setUid(target.getUid());
			if (role == AlRoleType.SOLDIER) {
				UserAllianceLog m_Ual = UserAllianceLog
						.getByPrimaryKey(new UserAllianceLogKey(target.getUid(), alliance.getAid()));
				int hisContribution = 0;
				if (m_Ual != null) {
					hisContribution = m_Ual.getTotalContribution();
				}
				if (hisContribution >= AllianceConfig.getMinCTB(AlRoleType.SERGEANCY)) {
					am.setRole(AllianceConfig.getRole(AlRoleType.SERGEANCY));
				} else {
					am.setRole(AllianceConfig.getRole(AlRoleType.SOLDIER));
				}
			} else {
				am.setRole(AllianceConfig.getRole(role));
			}
			am.setJointime(TimeUtil.getUtcNowMillis());
			am.insert();
		}
		alliance.addMember();
		target.setAid(alliance.getAid());
		AllianceEventDispatch.onAllianceMemberJoin(source, target, alliance, am, joinType);
		AllianceManager.getInstance().addAllianceUser(target);
		return am;
	}

	/**
	 * 创建联盟
	 */
	public static ISFSObject createAlliance(UserProfile userProfile, String name, String declar, int joinLimit)
			throws WW2Exception {
		// 检查用户是否已加入联盟
		if (userProfile.isJoinAlliance()) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_ALREADY_JOIN);
		}

		if (name == null || (name != null && name.isEmpty())) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NAME_ILLEAGUE);
		}

		//		// 匹配 汉字,数字,英文以及下划线 '_'
		//		String regex = "(?! )(?!.*? $)[^`~!@#\\$%\\^&\\*\\(\\)-=_\\+\\[\\]\\{\\}\\|;':\",\\./<>\\?]{2,20}";
		//		if (!Pattern.matches(regex, name)) {
		//			ISFSObject backObj = new SFSObject();
		//			backObj.putUtfString("aName", name);
		//			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NAME_ILLEAGUE, backObj);
		//		}

		// 联盟开启条件
		if (userProfile.getMissionManager().isFirst(AllianceConfig.getCreateMissionId())) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_NO_PERMISSION);
		}

		//		// 等级限制
		//		if (!AllianceConfig.isCreateLvLimit(userProfile.getUserInfo().getLevel())) {
		//			throw new WW2Exception(WW2ExceptionCode.USER_LEVEL_NOT_ENOUGH);
		//		}

		// 资源条件
		//		ISFSObject resObj = AllianceConfig.getCreateResource();
		//		if (!userProfile.getResManager().isResEnoughMulti(resObj)) {
		//			throw new WW2Exception(WW2ExceptionCode.USER_RES_NOT_ENOUGH);
		//		}

		// 检查联盟存在情况
		if (isAllianceExists(name)) {
			throw new WW2Exception(WW2ExceptionCode.ALLIANCE_ALREADY_EXIST);
		}

		Alliance ret = new Alliance();
		ret.setAid(UUIDGenerator.nextAllianceId());
		ret.setOwnerUid(userProfile.getUid());
		ret.setName(name);
		ret.setCreatetime(TimeUtil.getUtcNowMillis());
		ret.setJoinlimit(joinLimit);
		ret.setDisband(false);
		ret.setDisbandtime(0);
		ret.setLevel(1);
		ret.setDeclar(declar);
		ret.setNotice("");
		ret.setCountry(userProfile.getCountry());
		ret.setCurmember(0);
		ret.insert();

		// addMember
		addAllianceMember(null, userProfile, ret, AlRoleType.LEADER, JoinType.CREATE_ALLIANCE);

		//		userProfile.getResManager().operResWithMaxCheck(resObj, false);
		//		userProfile.getResManager().update();
		//		userProfile.getResManager().sync();

		AllianceManager.getInstance().addAlliance(ret);

		return getAllianceData(userProfile, ret);
	}

	/**
	 * 联盟成员占领一个据点
	 * @param originAid 原占领联盟id
	 */
	public static final void allianceMemberOccBase(String aid, String originAid) {
		Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
		if (alliance != null) {
			alliance.getAllianceWMDataManager().occBase();
		}
		// 原占领联盟丢失据点
		if (!StringUtils.isBlank(originAid)) {
			Alliance originAlliance = AllianceManager.getInstance().getAlliance(originAid);
			if (originAlliance != null) {
				originAlliance.getAllianceWMDataManager().lostBase();
			}
		}
	}

	/**
	 * 联盟成员防御一个据点
	 */
	public static final void allianceMemberDefBase(String aid) {
		Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
		if (alliance != null) {
			alliance.getAllianceWMDataManager().defendBase();
		}
	}

	/**
	 * 联盟占领城池
	 */
	public static final void allianceOccCity(String aid, String originAid) {
		Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
		if (alliance != null) {
			alliance.getAllianceWMDataManager().occCity();
		}
		// 原占领联盟丢失(城池)
		Alliance originAlliance = AllianceManager.getInstance().getAlliance(originAid);
		if (originAlliance != null) {
			originAlliance.getAllianceWMDataManager().lostCity();
		}
	}

	/**
	 * 联盟防御城池
	 */
	public static final void allianceDefCity(String aid) {
		Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
		if (alliance != null) {
			alliance.getAllianceWMDataManager().defendCity();
		}
	}

	/**
	 * 获取联盟排行(根据不同的field来排)
	 */
	public static final ISFSArray getAllAllianceRanking(AlWMDataFields field, int start, int count) {
		List<ScoredValue<String>> result = AllianceManager.getInstance().getCacheAlWorldMapTable()
				.sort(field.getValue(), start, count, true);
		ISFSArray ref = new SFSArray();
		int ranking = 1;
		for (ScoredValue<String> data : result) {
			ISFSObject obj = new SFSObject();
			obj.putInt("count", (int) data.score);
			obj.putInt("ranking", ranking++);
			String aid = data.value;
			obj.putUtfString("aid", aid);
			Alliance alliance = AllianceManager.getInstance().getAlliance(aid);
			if (alliance == null) {
				logger.warn("Alliance {} not found", aid);
				continue;
			}
			obj.putUtfString("aName", alliance.getName());
			int leaderUid = alliance.getOwnerUid();
			UserProfile leaderProfile = UserService.getInstance().getUserProfile(leaderUid);
			obj.putUtfString("leaderName", leaderProfile.getNickname());
			obj.putUtfString("country", leaderProfile.getCountry());
			ref.addSFSObject(obj);
		}
		return ref;
	}

	/**
	 * 获取<b>指定联盟</b>的排名信息
	 * @param aid 指定联盟id
	 * @param field 排序列
	 */
	public static final ISFSObject getAllianceRank(String aid, AlWMDataFields field) {
		ISFSObject ref = SFSObject.newInstance();
		KeyValue<Integer, Double> result = AllianceManager.getInstance().getCacheAlWorldMapTable()
				.rank(field.getValue(), RedisUtil.genericKey(aid), true);
		if (result != null) {
			ref.putInt("ranking", result.key);
			ref.putInt("count", result.value.intValue());
		}
		return ref;
	}

	/**
	 * 用户贡献<br>
	 * 若联盟升级则触发事件
	 */
	public static final void onContribute(UserProfile userProfile, ISFSObject resObj, ContributeType type) {
		// 根据捐献资源换算贡献值,然后加进去
		int val = 0;
		for (String key : resObj.getKeys()) {
			int res = resObj.getInt(key);
			val += Math.round(res * AllianceConfig.getContributeRatio(key)); // 四舍五入
		}

		/*
		 * 用户贡献度
		 */
		UserAllianceLog m_AlContributionLog = UserAllianceLog
				.getByPrimaryKey(new UserAllianceLogKey(userProfile.getUid(), userProfile.getAid()));
		if (m_AlContributionLog == null) {
			m_AlContributionLog = new UserAllianceLog();
			m_AlContributionLog.setAid(userProfile.getAid());
			m_AlContributionLog.setUid(userProfile.getUid());
			switch (type) {
			case BASE_ENHANCE_DONATE:
			case BASE_UPGRADE_DONATE:
				m_AlContributionLog.setBaseContribution(val);
				break;
			case PAYMENT:
				m_AlContributionLog.setPayContribution(val);
				break;
			}
			m_AlContributionLog.insert();
		} else {
			switch (type) {
			case BASE_ENHANCE_DONATE:
			case BASE_UPGRADE_DONATE:
				m_AlContributionLog.setBaseContribution(m_AlContributionLog.getBaseContribution() + val);
				break;
			case PAYMENT:
				m_AlContributionLog.setPayContribution(m_AlContributionLog.getPayContribution() + val);
				break;
			}

			m_AlContributionLog.update();
		}

		AllianceMember m_Am = AllianceMember.getByUid(userProfile.getUid());
		if (m_Am == null) {
			return;
		}
		switch (type) {
		case BASE_ENHANCE_DONATE:
		case BASE_UPGRADE_DONATE:
			m_Am.setBaseContribution(m_Am.getBaseContribution() + val);
			break;
		case PAYMENT:
			m_Am.setPayContribution(m_Am.getPayContribution() + val);
			break;
		}

		UserEventDispatch.onUserAllianceContributeChanged(userProfile, m_AlContributionLog, m_Am, val, type);

		// 之后更新
		m_Am.update();

		/*
		 * 联盟贡献度
		 */
		Alliance alliance = AllianceManager.getInstance().getAlliance(userProfile.getAid());
		if (alliance == null) {
			logger.error("Alliance [{}] not found!", userProfile.getAid());
			return;
		}
		alliance.setCurcontribution(alliance.getCurcontribution() + val);
		alliance.setHiscontribution(alliance.getHiscontribution() + val);

		AllianceEventDispatch.onAllianceContributionChanged(userProfile, alliance, val, type);

		alliance.update();
	}
}
